/*****************************************************************************
 * $LastChangedDate: 2012-03-04 10:40:32 -0500 (Sun, 04 Mar 2012) $
 * @file
 * @author  Jim E. Brooks  http://www.palomino3d.org
 * @brief   Shader functions.
 * @remarks For uniforms that change, create an instance of the template class Uniform<>.
 *          For uniforms assigned only once, use the function SetShaderUniform().
 *//*
 * LEGAL:   COPYRIGHT (C) 2009 JIM E. BROOKS
 *          THIS SOURCE CODE IS RELEASED UNDER THE TERMS
 *          OF THE GNU GENERAL PUBLIC LICENSE VERSION 2 (GPL 2).
 *****************************************************************************/

#ifndef SHADER_SHADER_FUNCS_HH
#define SHADER_SHADER_FUNCS_HH 1

#include "gfx/rgba.hh"
using namespace gfx;
#include "graph/typedefs.hh"
using namespace graph;
#include <osg/Node>
#include <osg/StateSet>
#include <osg/Program>
#include <osg/Uniform>

namespace shader {

void DisableShader( osg::StateSet& stateSet );
void ResetShaderUniformsForModel( Node& node );
void ResetShaderUniformsForRootNode( Node& node );
void SetShaderFog( Node& node, const fp fogDensity, const RGBA fogColor );

/*****************************************************************************
 * Convenience function to assign a uniform to a node.
 * This is slow -- it's only meant for one-time assignment of a uniform.
 * If a uniform will be changed frequently, instead use "new Uniform".
 *****************************************************************************/
template<typename T>
void SetShaderUniform( const string& uniformName, const T& val, RefPtr<osg::StateSet> stateset )
{
    // Try to change existing uniform, else create it.
    SafePtr<osg::Uniform> uni = stateset->getUniform( uniformName );
    if ( uni != NULL )
        uni->set( val );
    else
        stateset->addUniform( new osg::Uniform( uniformName.c_str(), val ) );
}

/*****************************************************************************
 * Convenience function to assign a uniform to a node.
 * This is slow -- it's only meant for one-time assignment of a uniform.
 * If a uniform will be changed frequently, instead use "new Uniform".
 *****************************************************************************/
template<typename T>
void SetShaderUniform( const string& uniformName, const T& val, Node& node )
{
    SetShaderUniform( uniformName, val, node.getOrCreateStateSet() );
}

} // namespace shader

#endif // SHADER_SHADER_FUNCS_HH
